package com.along.study.proxy;

import com.along.study.Config.ProxyConstant;
import com.along.study.common.CustomMsg;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Set;

@Slf4j
public class ServerHandler extends SimpleChannelInboundHandler<CustomMsg> {


    //收到客户端消息
    @Override
    public void channelRead0(ChannelHandlerContext ctx, CustomMsg msg) throws Exception {
        byte type = msg.getType();
        switch (type) {
            case CustomMsg.TYPE_CONNECT:
                String vid = new String(msg.getData());
                if (StringUtil.isNullOrEmpty(vid) || "client".equals(vid)) {
                    String clientId = new String(msg.getFrom()).trim();
                    ctx.channel().attr(ProxyConstant.CLIENT_CODE).set(clientId);
                    ProxyConstant.clientChannelMap.put(clientId,ctx.channel());
                    log.info("有新客户端{}接入进来了",clientId);
                } else {
                    // 绑定访客和客户端的连接
                    Channel visitorChannel = ProxyConstant.visitor_channel.get(vid);
                    if (null != visitorChannel) {
                        ctx.channel().attr(ProxyConstant.VID).set(vid);
                        ProxyConstant.chient_channel.put(vid, ctx.channel());
                        // 通道绑定完成可以读取访客数据
//                        visitorChannel.config().setOption(ChannelOption.AUTO_READ, true);
                        VisitorPreHandler handler = (VisitorPreHandler)visitorChannel.pipeline().get(ProxyConstant.HANDLER_ONE);
                        handler.doNextHandlerRead();
                    }
                }
                break;
            case CustomMsg.TYPE_HEARTBEAT:
                log.info("收到{}心跳",new String(msg.getFrom()));
                break;
            case CustomMsg.TYPE_SEARCH:
                //查询在线客户端
                Set<String> set = ProxyConstant.clientChannelMap.keySet();
                CustomMsg resp = new CustomMsg();
                resp.setType(CustomMsg.TYPE_SEARCH);
                resp.setData(set.toString().getBytes());
                ctx.channel().writeAndFlush(resp);
                break;
            case CustomMsg.TYPE_TRANSFER:
                // 把数据转到用户服务
                ByteBuf buf = ctx.alloc().buffer(msg.getData().length);
                buf.writeBytes(msg.getData());

                String visitorId = ctx.channel().attr(ProxyConstant.VID).get();
                Channel vchannel = ProxyConstant.visitor_channel.get(visitorId);
                if (null != vchannel) {
                    vchannel.writeAndFlush(buf);
                }
                break;
            case CustomMsg.TYPE_DISCONNECT:
                String disVid = new String(msg.getData());
                ProxyConstant.clearVccVvcAndClose(disVid);
                break;
        }
    }

    //有客户端连接
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    //客户端断开连接
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String vid = ctx.channel().attr(ProxyConstant.VID).get();
        if (StringUtil.isNullOrEmpty(vid)) {
            super.channelInactive(ctx);
            return;
        }
        Channel visitorChannel = ProxyConstant.visitor_channel.get(vid);
        if (visitorChannel != null && visitorChannel.isActive()) {
            // 数据发送完成后再关闭连接，解决http1.0数据传输问题
            visitorChannel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
            visitorChannel.close();
        } else {
            ctx.channel().close();
        }
        ProxyConstant.clearVccVvc(vid);
        super.channelInactive(ctx);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        String vid = ctx.channel().attr(ProxyConstant.VID).get();
        if(StringUtil.isNullOrEmpty(vid)) {
            super.channelWritabilityChanged(ctx);
            return;
        }
        Channel visitorChannel = ProxyConstant.visitor_channel.get(vid);
        if (visitorChannel != null) {
            visitorChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
        }

        super.channelWritabilityChanged(ctx);
    }

    //客户端发生异常
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        String clientId = ctx.channel().attr(ProxyConstant.CLIENT_CODE).get();
        ProxyConstant.clientChannelMap.remove(clientId);
        Channel channel = ctx.channel();
        if(channel.isActive())ctx.close();
        log.info("客户端异常断开，移除客户端{}",clientId);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            switch (event.state()) {
                case READER_IDLE:
                    //在60秒没收到客户端发来的消息就移除
                    String clientId = ctx.channel().attr(ProxyConstant.CLIENT_CODE).get();
                    ProxyConstant.clientChannelMap.remove(clientId);
                    ctx.channel().close();
                    log.info("移除客户端{}",clientId);
                    break;
                case WRITER_IDLE:
                    break;
                case ALL_IDLE:
                    break;
            }
        }
    }


}
